package com.dlc.felear.xiaoensale.deviceControlSf;

import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.dlc.felear.xiaoensale.constant.Constant;
import com.dlc.felear.xiaoensale.dlc_serial_port.DlcSerialPortClient;
import com.dlc.felear.xiaoensale.factory.CmdList;
import com.dlc.felear.xiaoensale.helper.JsonHelper;

import org.simple.eventbus.EventBus;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 食材下料盒子控制
 */
public class LiaoheControl implements Handler.Callback {
    private static final String TAG = "LiaoheControl";
    private static final int WHAT_TIMEOUT_GT = 11524;
    private static final int WHAT_CCWZ = 12524;
    private static final int WHAT_CACHE = 12224;
    public static int ALL_TIMEOUT = 20000;
    private static final int OPEN_DELAY = 5000;
    private static final int WHAT_DELAYTIME = 11211;
    private static final int WHAT_SENSOR_TIMEOUT = 1111;
    public static final int SENSOR_DOOR_1_CLOSE = 7;
    private static final int SENSOR_DOOR_1_OPEN = 8;
    public static final int SENSOR_DOOR_2_CLOSE = 9;
    public static final int SENSOR_DOOR_2_OPEN = 10;
    public static final int SENSOR_DOOR_3_CLOSE = 11;
    public static final int SENSOR_DOOR_3_OPEN = 12;
    public static final int SENSOR_DOOR_4_CLOSE = 13;
    public static final int SENSOR_DOOR_4_OPEN = 14;
    public static final int SENSOR_DOOR_5_CLOSE = 15;
    public static final int SENSOR_DOOR_5_OPEN = 16;
    private String serialNum;
    private SensorStatusInfo sensorStatusInfo;
    private Map<Integer, Integer> cacheCmds;
    private ThreadPoolExecutor scheduledThreadPool;
    private int openDelay = 10;
    private int closeDelay = 6;
    private GuotiActionControl guotiActionControl;
    private boolean ccFlag = false;
    private int position = 1;
    private Handler handler;
    private long tempGz = -1;
    private HashMap<Integer, Integer> sensorMpas = new HashMap<>();
    private HashMap<Integer, Boolean> openStatus = new HashMap<>();
    private boolean singgleDebug = false;

    public LiaoheControl(Map<Integer, Integer> cacheCmds, String serialNum, SensorStatusInfo sensorStatusInfo,
                         ThreadPoolExecutor scheduledThreadPool,
                         GuotiActionControl guotiActionControl) {
        this.cacheCmds = cacheCmds;
        this.serialNum = serialNum;
        this.sensorStatusInfo = sensorStatusInfo;
        this.scheduledThreadPool = scheduledThreadPool;
        this.guotiActionControl = guotiActionControl;
        handler = new Handler(this);
        for (int i = 7; i < 17; i++) {
            sensorMpas.put(i, 0);
        }
    }

    public void allCloseAndOpen(int value) {
        singgleDebug = true;
        ccFlag = false;
        if (value == 10) {
            closeAllGz();
        } else if (value == 11) {
            openAllGz();
        }
    }

    public void openGz(int num, int sec) {
        log("openGz 格子：" + num + " 打开时间:" + sec + " 间隔:" + ((System.currentTimeMillis() - tempGz) / 1000), 0);
        tempGz = System.currentTimeMillis();
        if (num == 10 || num == 11) {
            allCloseAndOpen(num);
            return;
        }
        if (num <= 0 || num > 4) {
            log("输入参数不符合规则", 1);
            return;
        }
        singgleDebug = false;
        num = num + 12;
        log("打开格子:" + num + " msec=" + sec + " position=" + position + " ccFlag=" + ccFlag, 0);
        if (!ccFlag) {
            openAction(num, "手动模式打开");
            return;
        }
        if (ccFlag && !guotiActionControl.gtIsYw()) {
            saveGz(num, sec);
            log("锅体不在炒菜位置，缓存指令并转动锅体" + JsonHelper.toJson(cacheCmds), 0);
            guotiActionControl.runPositionJsc();
            return;
        }
        openAction(num, "炒菜模式且符合条件打开");
    }

    private void delayOpen(int num, int msec) {
        Message message = new Message();
        message.what = WHAT_CACHE;
        message.arg1 = num;
        message.arg2 = msec;
        handler.sendMessageDelayed(message, OPEN_DELAY);
    }

    private synchronized void saveGz(int num, int msec) {
        cacheCmds.put(num, msec);
        log("缓存格子信息:" + JsonHelper.toJson(cacheCmds) + " cacheCmdsHashCode:" + cacheCmds.hashCode(), 0);
    }


    /**
     * 打开所有格子
     */
    private void openAllGz() {
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE) != 1) {
            openGezi(13, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE) != 1) {
            openGezi(14, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE) != 1) {
            openGezi(15, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE) != 1) {
            openGezi(16, openDelay);
        }
    }

    /**
     * 关闭所有格子
     */
    private void closeAllGz() {
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_OPEN) != 1) {
            openGezi(13, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_OPEN) != 1) {
            openGezi(14, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_OPEN) != 1) {
            openGezi(15, openDelay);
        }
        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_OPEN) != 1) {
            openGezi(16, openDelay);
        }
    }

    private int getDoByDI(int di) {
        int temp = -1;
        if (di == 7 || di == 8) {
            temp = 13;
        }
        if (di == 9 || di == 10) {
            temp = 14;
        }
        if (di == 11 || di == 12) {
            temp = 15;
        }
        if (di == 13 || di == 14) {
            temp = 16;
        }
        if (di == 15 || di == 16) {
            temp = 17;
        }
        return temp;
    }


    /**
     * 打开格子
     *
     * @param num
     */
    private void openAction(final int num, String msg) {
        log("openAction 打开：" + num + " ccFlag:" + ccFlag + " 锅体位置:" +
                guotiActionControl.getPositon() + " POSITION_YD:" + GuotiActionControl.POSITION_YD + " 触发来源:" + msg, 0);
        try {
            if (guotiActionControl.gtIsYw()) {
                openStatus.put(num, true);
                openGezi(num, openDelay);
            } else {
                log("锅体没有在加食材位置", 1);
            }
            sendTimeDelay(num, WHAT_SENSOR_TIMEOUT, ALL_TIMEOUT);
            sendTimeDelay(num, WHAT_TIMEOUT_GT, ALL_TIMEOUT);
        } catch (Exception e) {
            log("openAndClose Exception:" + e.getMessage(), 0);
        }
    }

    private void closeAction(final int num, String msg) {
        log("打开：" + num + " ccFlag:" + ccFlag + " 锅体位置:" + guotiActionControl.getPositon() + " 触发来源:" + msg, 0);
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
//                    log("格子：" + num + "正在打开", 0);
                    openStatus.put(num, true);
                    openGezi(num, openDelay);
                } catch (Exception e) {
                    log("openAndClose Exception:" + e.getMessage(), 0);
                }
            }
        });
    }

    private void openGezi(int num, int openDelay) {
        if (openDelay == 0) {
            sendCmd(CmdList.OpenDO(num, openDelay));
            return;
        }
        log("openGezi num:" + (num - 12), 0);
        if (getOpenSensorStatus(num)) {
            sendCmd(CmdList.OpenDO(num, openDelay));
        }
    }

    private boolean getOpenSensorStatus(int num) {
        boolean temp = true;
//        if(num==13){
//            temp=(sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE)==0);
//        }
//        if(num==14){
//            temp=(sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE)==0);
//        }
//        if(num==15){
//            temp=(sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE)==0);
//        }
//        if(num==16){
//            temp=(sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE)==0);
//        }
//        if(num==17){
//            temp=(sensorStatusInfo.getIoStatus(SENSOR_DOOR_5_CLOSE)==0);
//        }
        Log.e(TAG, "getOpenSensorStatus num=" + num + " temp=" + temp);
        return temp;
    }

//    private void removeGzCache(int num, String msg) {
////        log("取消格子缓存信息：" + num + "(" + JsonHelper.toJson(cacheCmds) + ")" + " 触发位置:" + msg, 0);
//        cacheCmds.remove(num);
//    }


    public void sensorStatus(int num) {
        try {
            log("传感器检测 num=" + num, 0);
            switch (num) {
                case SENSOR_DOOR_1_OPEN:
                case SENSOR_DOOR_2_OPEN:
                case SENSOR_DOOR_3_OPEN:
                case SENSOR_DOOR_4_OPEN:
                    saveSensorStatus(num, 1);
                    log("singgleDebug:" + singgleDebug + " 格子门关传感器状态:" + sensorStatusInfo.getIoStatus(num - 1)
                            + "是否关闭过:" + getOpenAction(getDoByDI(num)), 0);
                    openGezi(getDoByDI(num), 0);
                    if (sensorStatusInfo.getIoStatus(num - 1) == 0 && !singgleDebug) {
                        if (getOpenAction(getDoByDI(num))) {
                            log("保持5秒打开状态，5秒后关闭", 0);
                            delayOpen(getDoByDI(num), -1);
                        } else {
                            log("没有开启动作或开启动作已过期", 0);
                        }
                    }
                    sendTimeDelay(getDoByDI(num), WHAT_CCWZ, 1000);
                    break;
                case SENSOR_DOOR_1_CLOSE:
                case SENSOR_DOOR_2_CLOSE:
                case SENSOR_DOOR_3_CLOSE:
                case SENSOR_DOOR_4_CLOSE:
                    openStatus.put(getDoByDI(num), false);
                    saveSensorStatus(num, 2);
                    delayClose(getDoByDI(num), 0);
                    zdgt(getDoByDI(num));
                    break;
                case GuotiActionControl.MAX_IO:
                    openCacheGzB();
                    break;

            }
        } catch (Exception e) {

        }
    }

    private boolean getOpenAction(int num) {
        if (openStatus.containsKey(num)) {
            return openStatus.get(num);
        }
        return false;
    }


    private void delayClose(final int num, final int mssc) {
        scheduledThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(mssc);
                    openGezi(num, 0);
                } catch (Exception e) {

                }
            }
        });

    }


    public void openCacheGzB() {
        try {
            log("锅体回到原点，开始打开格子：" + JsonHelper.toJson(cacheCmds), 0);
            for (Integer num : cacheCmds.keySet()) {
                log("遍历格子信息,num=" + (num), 0);
                openAction(num, "openCacheGzB:" + (num - 12));
            }
        } catch (Exception e) {
            log(e.getMessage(), 0);
        }
    }

    private void reTurnCcPosition(int ioNum) {
        log("门关闭传感器有感应,开始锅转动到炒菜位置：" + ioNum +
                " 格子" + " 总共耗时:" + (System.currentTimeMillis() - tempGz) / 1000 + "秒", 0);
        if (ccFlag) {
            cacheCmds.clear();
            guotiActionControl.runPositionCc(guotiActionControl.getCcLevelPosition());
            handler.removeMessages(WHAT_TIMEOUT_GT);
        }
    }

    private void sendTimeDelay(int num, int what, long delayMillis) {
        if (WHAT_SENSOR_TIMEOUT == what) {
            log("取消上次的监测传感器任务,num:" + num + " what:" + what, 0);
            what = WHAT_SENSOR_TIMEOUT + num;
            handler.removeMessages(what);
        }
        if (what == WHAT_TIMEOUT_GT) {
            handler.removeMessages(what);
        }
        Message message = Message.obtain();
        message.what = what;
        message.arg1 = num;
        handler.sendMessageDelayed(message, delayMillis);
    }

    public boolean gzAllClosed(String msg) {
        return true;
    }


    private void sendCmd(byte[] data) {
//        log("data=" + HexUtil.bytes2HexString(data));
        DlcSerialPortClient.getInstance().send(serialNum, data);
    }

    private void log(String log, int flag) {
        if (!TextUtils.isEmpty(log)) {
            Log.e(TAG, log);
        }
        if (flag == 1) {
            EventBus.getDefault().post(log, Constant.DEVICE_STATUS_MSG_SHOW);
        }
    }

    /**
     * @param flag f炒菜结束 t炒菜开始
     */
    public void isChaocaiStatus(boolean flag) {
//        log("炒菜标志:" + flag, 0);
        ccFlag = flag;
        if (flag) {
            cacheCmds.clear();
            log("清除格子缓存信息", 0);
        }
    }


    public void clearData() {
        cacheCmds.clear();
    }

    public void allStop() {
        clearData();
    }

    public void setPosition(int flag, int puls) {
        if (flag == 3) {
            log("到达位置 开始下格子:" + flag + " puls=" + puls, 0);
            sensorStatus(flag);
        }
    }


    @Override
    public boolean handleMessage(Message message) {
//        log("handleMessage: what=" + message.what, 0);
        if (message.what == WHAT_CACHE) {
            int num = message.arg1;
            if (message.arg2 == -1) {
                openStatus.put(message.arg1, false);
                closeAction(num, "handleMessage=" + message.arg2);
            } else if (guotiActionControl.gtIsYw()) {
                openAction(num, "handleMessage=" + message.arg2);
            }
        } else if (message.what == WHAT_DELAYTIME) {
            int num = message.arg1;
            log("开始关闭：" + num + " 格子", 0);
            openGezi(num, closeDelay);
            sendTimeDelay(num, WHAT_TIMEOUT_GT, 2000);
        } else if (message.what == (WHAT_SENSOR_TIMEOUT + message.arg1)) {
            log("传感器检测监听 num:" + message.arg1, 0);
            superSensor(message.arg1 - 12);
        } else if (message.what == WHAT_TIMEOUT_GT && ccFlag) {
            //打开格子超时处理逻辑
            openStatus.put(message.arg1, false);
            reTurnCcPosition(message.arg1);
        } else if (message.what == WHAT_CCWZ && ccFlag) {
            //检测到关闭格子动作，提前转动锅体到炒菜位置
            zdgt(message.arg1);
        }
        return false;
    }


    private void zdgt(int num) {
        if (pdzdtj(num)) {
            handler.removeMessages(num);
            reTurnCcPosition(num);
        }
    }

    /**
     * 判断锅转动条件
     *
     * @param num
     */
    private boolean pdzdtj(int num) {
        boolean flag = false;
        if (num == 1 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE) == 1 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE) == 1 &&
                sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE) == 1) {
            flag = true;
        }
        if (num == 2 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE) == 1 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE) == 1 &&
                sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE) == 1) {
            flag = true;
        }
        if (num == 3 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE) == 1 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE) == 1 &&
                sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE) == 1) {
            flag = true;
        }
        if (num == 4 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE) == 1 && sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE) == 1 &&
                sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE) == 1) {
            flag = true;
        }
        if (flag == false) {
            boolean temp = false;
            for (Integer num1 : openStatus.keySet()) {
                if (openStatus.get(num1)) {
                    temp = true;
                    break;
                }
            }
            flag = !temp;
//            log("重置锅体转动条件: flag=" + flag + " temp=" + temp, 0);
        }
        log("锅体转动条件: flag=" + flag, 0);
        return flag;
    }

    private void superSensor(int gzNum) {
        String msg = "";
        switch (gzNum) {
            case 1:
                msg = getSensorMsg(gzNum);
                break;
            case 2:
                msg = getSensorMsg(gzNum);
                break;
            case 3:
                msg = getSensorMsg(gzNum);
                break;
            case 4:
                msg = getSensorMsg(gzNum);
                break;
            case 5:
                msg = getSensorMsg(gzNum);
                break;
        }
//        log("格子传感器超时检测:" + msg + " gzNum:" + gzNum, 0);
        if (!TextUtils.isEmpty(msg)) {
            log(msg, 0);
        }
    }

    private String getSensorMsg(int gzNum) {
        log("getSensorMsg :" + gzNum, 0);
        String temp = "";
        if (gzNum == 1) {
            temp = getHandleMsg(gzNum, sensorMpas.get(SENSOR_DOOR_1_CLOSE), sensorMpas.get(SENSOR_DOOR_1_OPEN));
            saveSensorStatus(SENSOR_DOOR_1_CLOSE, 0);
            saveSensorStatus(SENSOR_DOOR_1_OPEN, 0);
        }
        if (gzNum == 2) {
            temp = getHandleMsg(gzNum, sensorMpas.get(SENSOR_DOOR_2_CLOSE), sensorMpas.get(SENSOR_DOOR_2_OPEN));
            saveSensorStatus(SENSOR_DOOR_2_CLOSE, 0);
            saveSensorStatus(SENSOR_DOOR_2_OPEN, 0);
        }
        if (gzNum == 3) {
            temp = getHandleMsg(gzNum, sensorMpas.get(SENSOR_DOOR_3_CLOSE), sensorMpas.get(SENSOR_DOOR_3_OPEN));
            saveSensorStatus(SENSOR_DOOR_3_CLOSE, 0);
            saveSensorStatus(SENSOR_DOOR_3_OPEN, 0);
        }
        if (gzNum == 4) {
            temp = getHandleMsg(gzNum, sensorMpas.get(SENSOR_DOOR_4_CLOSE), sensorMpas.get(SENSOR_DOOR_4_OPEN));
            saveSensorStatus(SENSOR_DOOR_4_CLOSE, 0);
            saveSensorStatus(SENSOR_DOOR_4_OPEN, 0);
        }
        return temp;
    }

    private void saveSensorStatus(int sensorNum, int flag) {
        sensorMpas.put(sensorNum, flag);
    }

    private String getHandleMsg(int num, int closeStatus, int openStatus) {
//        log("num:" + num + " closeStatus:" + closeStatus + " openStatus:" + openStatus, 0);
        String temp = "";// 1 open  2 close
        int add = closeStatus + openStatus;
        if (add == 0) {
            temp = "第" + num + "都没有触发格子";
        } else if (add < 3) {
            temp = "第" + num + (add == 1 ? "格子门关状态传感器没有触发" : "格子门开状态传感器没有触发");
        }
        return temp;
    }

    public String getErrorMsg() {
        String msg = "";
//        if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_1_CLOSE) != 1) {
//            msg = "第1个格子门没有关到位";
//        } else if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_2_CLOSE) != 1) {
//            msg = "第2个格子门没有关到位";
//        } else if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_3_CLOSE) != 1) {
//            msg = "第3个格子门没有关到位";
//        } else if (sensorStatusInfo.getIoStatus(SENSOR_DOOR_4_CLOSE) != 1) {
//            msg = "第4个格子门没有关到位";
//        }
        return msg;
    }
}




